Git 常用命令
========================

版本标识
--------

Git 可以用多种方法标识一个版本：

* commit hash
* 本地分支名，如 master
* 远程分支名，如 origin/master
* HEAD 和 HEAD 之前n个版本 HEAD~n
* tag: 用git tag显示所有的tag

本地仓库
-------------

* 初始化本地仓库：git init
* 暂存修改：git add

  - 注意此时修改并未提交，要提交修改执行 git commit
  - 如果在 git add 之后又修改了已暂存的文件，可以再次执行 git add 暂存最新版本的文件
* 查看修改：git diff

  - 如修改已用 git add 暂存，则加 ``--cached`` 参数，即 git diff --cached
* 查看仓库历史记录：git log

  - 每条历史记录为一个 commit，代表一个版本，commit 的散列值可用于标识版本
* 检出版本 deadbeef: git checkout deadbeef
* 修改当前版本：git commit --amend

  - 将暂存的修改提交，并且和最新版本合并
  - 如果没有文件的修改，``git commit --amend`` 的作用是修改提交描述

分离头指针相关
-----------------

对于分离的头指针，可以在上面创建分支。

如果在分离的头上做了修改，又不小心检出了其他提交，可以使用 ``git reflog`` 找回丢失的提交。


分支相关
--------

* 创建名为 test 的本地分支：git branch test

  - 此时 git 仓库所在的分支仍为操作前分支，要切换到 test 分支，需要 git checkout
  - test 分支的最终版本是执行 git branch 前的版本
* 检出版本 deadbeef 并以其为最终版本创建一个名为 test 的分支：git checkout deadbeef -b test

  - 此时 git 仓库切换到 test 分支，版本为 deadbeef


变基操作
---------

变基操作 git rebase 是 Git 的一个重要操作，“把版本A变基到版本B上”的含义是将版本 B 没有而版本 A 有的修改应用到 B 上，得到一个新的版本。

* git rebase v1.0: 把当前版本变基到 v1.0 标识的版本上，变基成功后，版本切换到变基后的版本
* git rebase -i v1.0: ``-i`` 表示交互式变基，命令执行后，会打开一个编辑器，让用户选择具体的操作，常用的有：

  - squash(s): 把当前的提交和前面的提交合并为一个提交
  - reword(r): 修改提交描述


远程仓库
--------

* 创建名为 origin 的远程仓库，地址为 ``https://example.com/hello``::

   git remote add origin https://example.com/hello

* 修改远程仓库 origin 的地址为 ``git@wehack.space:hello``::

   git remote set-url origin git@wehack.space:hello

* git fetch 和 git pull 的区别：git pull 相当于 git fetch 之后 merge. 如果只想从远程仓库获取一个 refspec 的内容及其历史，但并不想 merge，可以用 git-fetch::

   git fetch origin master

合并操作
---------

* git cherry-pick deadbeef: 将 deadbeef 标识的 **一个提交** 应用到当前版本上，得到一个新的版本
* git merge deadbeef: 将 deadbeef 标识的版本合并到当前版本

  - 如果存在合并冲突，手动解决冲突后，会产生一个合并提交
  - 建议的操作是先变基，在变基的过程中解决冲突，再合并，这样不会产生一个合并提交


其他
----

AUR 的软件包中，可以用以下命令描述一个用 Git 作版本管理的软件的版本：

* git rev-list --count HEAD: 查看从初始版本到当前版本的提交个数
* git describe --always 可以用于描述一个版本

如果不需要获取一个仓库的所有历史，可以用 ``git clone --depth=1``.

GitHub 操作建议
----------------

提交 pull request 时，建议创建一个新的分支，并且用 ``git rebase -i`` 变基到上游仓库的主分支（一般为master）上。如果对 pull request 中的提交用 ``git commit --amend`` 进行了修改，可以使用 ``git push --force``.

合并 pull request 时，使用 ``Rebase and merge`` 或 ``Squash and merge`` ，而不是使用 ``Create a merge commit`` 方案。如果有变基冲突而不能用 ``Rebase and merge``,则进行手动操作，将 pull request 的版本 pull 至本地，然后进行手动 rebase 或 cherry-pick 操作。
